package com.genius.Genius.Element.Byte;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

public class ByteUtil {

    public static byte[] objectToByte(Object obj){
        byte[] bytes = {};
        try( ByteArrayOutputStream bo = new ByteArrayOutputStream();
             ObjectOutputStream oo = new ObjectOutputStream(bo)) {
            oo.writeObject(obj);
            bytes = bo.toByteArray();
        }catch (Exception e){
            e.printStackTrace();
        }
        return bytes;
    }

    public static Object byteToObject(byte[] bytes){
        Object obj = null;
        try (ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
             ObjectInputStream oi = new ObjectInputStream(bi)){
            obj = oi.readObject();
        }catch (Exception e){
            e.printStackTrace();
        }
        return obj;
    }

    public static byte[] short2byte(short s){
        byte[] b = new byte[2];
        for(int i = 0; i < 2; i++){
            int offset = 16 - (i+1)*8; //因为byte占4个字节，所以要计算偏移量
            b[i] = (byte)((s >> offset)&0xff); //把16位分为2个8位进行分别存储
        }
        return b;
    }

    public static short byte2short(byte[] data){
        short l = 0;
        for (int i = 0; i <2 ; i++) {
            l<<=8;
            l |= (data[i]&0xff);
        }
        return l;
    }

    public static byte[] short2Byte(short value) {
        return ByteBuffer.allocate(Short.SIZE / Byte.SIZE).putShort(value).array();
    }

    public static byte[] int2Byte(int value){
        return ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(value).array();
    }

    public static byte[] long2Byte(long value){
        return ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(value).array();
    }

    public static int parseInt(byte[] buf){
        return ByteBuffer.wrap(buf,0,4).getInt();
    }

    public static long parseLong(byte[] buf){
        ByteBuffer buffer = ByteBuffer.wrap(buf, 0, 8);
        return buffer.getLong();
    }

    public static short parseShort(byte[] buf) {
        ByteBuffer buffer = ByteBuffer.wrap(buf, 0, 2);
        return buffer.getShort();
    }

    public static byte[] quickParseBytes(Object obj){
        if(obj==null){
            return new byte[]{};
        }
        if(obj.getClass() == String.class){
            String str = (String)obj;
            return str.getBytes();
        } else if(obj.getClass() == Double.class || obj.getClass() == Long.class){
            long var = obj.getClass() == Double.class?Double.doubleToLongBits((double)obj):(long)obj;
            return long2Byte(var);
        }else if(obj.getClass() == Float.class || obj.getClass() == Integer.class){
            int var = obj.getClass() == Float.class?Float.floatToIntBits((float)obj):(int)obj;
            return int2Byte(var);
        }else if(obj.getClass() == Byte.class || obj.getClass() == Boolean.class){
            byte var = (byte)obj;
            if(obj.getClass() == Boolean.class){
                var = (byte)((boolean)obj?1:0);
            }
            return new byte[]{var};
        }else{
            return objectToByte(obj);
        }
    }

    public static Object quickParseObject(byte[] bytes,Class clazz){
        if(bytes==null||bytes.length==0){
            return null;
        }
        if(clazz == String.class){
            return StandardCharsets.UTF_8.decode(ByteBuffer.wrap(bytes));
        } else if(clazz == Double.class || clazz == Long.class){
            long var = ByteUtil.parseLong(bytes);
            if(clazz == Double.class){
                return Double.longBitsToDouble(var);
            }
            return var;
        }else if(clazz == Float.class || clazz == Integer.class){
            int var = ByteUtil.parseInt(bytes);
            if(clazz == Float.class){
                return Float.intBitsToFloat(var);
            }
            return var;
        }else if(clazz == Byte.class || clazz == Boolean.class){
            byte var =  bytes[0];
            if(clazz == Boolean.class){
                return var == 1;
            }
            return var;
        }else{
            return byteToObject(bytes);
        }
    }
}
